/**
 * <p>文件名:		MD5.java</p>
 * <p>版权:		CopyrightTag</p>
 * <p>公司:		CompanyTag</p>
 * @author		周华彬(zhouhuabin@ctfo.com)
 */

package com.caits.lbs.framework.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.log4j.Logger;

import com.caits.lbs.framework.log.CommonLogFactory;

/**
 * <p>
 * MD5
 * </p>
 * <p>
 * MD5生成器
 * </p>
 * RFC 1321 Test Suilt 检验用例<br>
 * MD5 ("") = d41d8cd98f00b204e9800998ecf8427e<br>
 * MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661<br>
 * MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72<br>
 * MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0<br>
 * MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b<br>
 * </p>
 * 
 * @author 周华彬(zhouhuabin@ctfo.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">版本号</th>
 *          <th width="100px">动作</th>
 *          <th * width="100px">修改人</th>
 *          <th width="100px">修改时间</th>
 *          </tr>
 *          <!-- 以 Table 方式书写修改历史 -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td>创建类</td>
 *          <td>周华彬</td>
 *          <td>2008-10-18 下午11:55:52</td>
 *          </tr>
 *          <tr>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          </tr>
 *          </table>
 */
public final class MD5 {

	protected static Logger log = CommonLogFactory.getLog();
	/**
	 * 构造器
	 */
	private MD5() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * 选择是否使用小写方式显示还是使用大写
	 * 
	 * @param fileAbsolutePath
	 * @param lowerCase
	 * @return 绝对不会返回NULL
	 */
	public static String encodeFile(String fileAbsolutePath) {
		String resultString = "";

		// 不论什麽异常，都不会影响计算，只是如果异常发生，那么该值为"",显然不是md5结果串
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			File file = new File(fileAbsolutePath);
			if (file.exists()) {
				FileInputStream in = new FileInputStream(file);
				byte[] fileBytes = new byte[(int) file.length()];
				in.read(fileBytes);

				resultString = ByteUtils.bytes2HexString(md.digest(fileBytes));
				in.close();
			}
		} catch (NoSuchAlgorithmException e) {
			log.error("没有此算法错误,msg="+e.getLocalizedMessage());
		} catch (FileNotFoundException e) {
			log.error("文件不存在错误,msg="+e.getLocalizedMessage());
		} catch (IOException e) {
			log.error("输出流错误,msg="+e.getLocalizedMessage());
		}

		return resultString;
	}

	/**
	 * 进行MD5编码，获得字节数组
	 * 
	 * @param origin
	 * @return
	 */
	public static byte[] encodeToBytes(String origin) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			return md.digest(origin.getBytes());
		} catch (Exception e) {
			log.error("无法获得MD5实例");
		}
		return new byte[0];
	}

	/**
	 * 把字符串进行MD5编码
	 * @param origin	原始字符串，用默认字符集
	 * @return
	 */
	public static String encode(String origin) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			return ByteUtils.bytes2HexString(md5.digest(origin.getBytes()));
		} catch (Exception e) {
			log.error("无法获得MD5实例");
			return "";
		}
	}

	/**
	 * 把数组进行MD5编码
	 * @param origin	原始数组
	 * @return
	 */
	public static byte[] encode(byte[] origin) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			return md5.digest(origin);
		} catch (Exception e) {
			log.error("无法获得MD5实例");
			return new byte[0];
		}
	}
	/**
	 * 根据算法名称进行加密
	 * 
	 * @param strSrc 要加密的字符串
	 * @param encName 加密名称.
	 * @return 加密后的串，是大写
	 */
	public static String encryptAny(String strSrc, String encName,String charSet) {
		MessageDigest md = null;
		String strDes = null;
		try {
			byte[] bt = strSrc.getBytes(charSet);
			if (encName == null || encName.equals("")) {
				encName = "MD5";
			}
			md = MessageDigest.getInstance(encName);
			md.update(bt);	//更新运算数组
			strDes = ByteUtils.bytes2HexString(md.digest()); // 运算并转换 to HexString
		} catch (NoSuchAlgorithmException e) {
			log.error("Invalid algorithm.");
			return null;
		}catch (Exception e) 
        {  
			log.error("encryptAny error,msg="+e.getLocalizedMessage());
	        return null;
	     } 
		return strDes;
	}
	/**
	 * 按指定字符编码进行md5加密字符串 
	 * @param str
	 * @param charSet
	 * @return 加密后的串，是小写
	 */
	@Deprecated
	public static String encryptMd5(String str, String charSet) 
    {  
        MessageDigest messageDigest = null;  
        try 
        {  
            messageDigest = MessageDigest.getInstance("MD5");  
            messageDigest.reset();  
            messageDigest.update(str.getBytes(charSet));  
        } 
        catch (Exception e) 
        {  
           return "";
        } 
        byte[] byteArray = messageDigest.digest();  
        StringBuffer md5StrBuff = new StringBuffer();  
        for (int i = 0; i < byteArray.length; i++) 
        {              
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)  
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));  
            else  
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));  
        }  
        return md5StrBuff.toString();  
    }

    /**
	 * FIXME
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		String strSrc="_input_charset=utf-8&account_name=北京掌行通信息技术有限公司&batch_fee=2&batch_no=201512240000004&batch_num=1&detail_data=1^zhou_hua_bin@163.com^周华彬^2.00^停呗提现&email=yuqing@chinatransinfo.com&notify_url=http://rtti.3322.org/payservice/alipay.do&partner=2088121216591811&pay_date=20151224&service=batch_trans_notifyb301u1i83edtxqa3c42zaj0zwo4ljrdj";
		String ret = encryptAny(strSrc, "sha-1","UTF-8");
		System.out.println("Use  any:"+encryptAny(strSrc, "md5","UTF-8"));	//32位
		System.out.println("Use  MD5:"+encryptMd5(strSrc, "UTF-8"));	//32位
		System.out.println("Use  SHA-1:"+ret);	//42位
		System.out.println("Use SHA-256:"+encryptAny(strSrc,"SHA-256","UTF-8"));//64位
	}

}
